package com.uobgroup.ews.uam.web;

import java.io.UnsupportedEncodingException;
import java.security.Principal;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import org.joda.time.format.DateTimeFormat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.util.UriUtils;
import org.springframework.web.util.WebUtils;

import com.uobgroup.ews.uam.core.domain.AccessControl;
import com.uobgroup.ews.uam.core.domain.RoleSubType;
import com.uobgroup.ews.uam.core.exception.CannotDeleteObjectException;
import com.uobgroup.ews.uam.core.service.AccessControlService;
import com.uobgroup.ews.uam.core.service.ReferenceService;
import com.uobgroup.ews.uam.core.service.RoleSubTypeService;
import com.uobgroup.ews.uam.web.dto.SearchAccessControl;

@RequestMapping("/rolesubtype")
@Controller
public class RoleSubTypeController {

	public static final String ROLE_SUB_TYPE_IS_USE = "Can't delete. Role SubType is assigned to role.";
	
   @Autowired
   private RoleSubTypeService roleSubTypeService;
   
   @Autowired
   private ReferenceService referenceService;
   
   @Autowired
   private AccessControlService accesscontrolServce;

   @Autowired
   private ReloadableResourceBundleMessageSource messageSource;

   @RequestMapping(method = RequestMethod.POST, produces = "text/html")
   public String create(@Valid RoleSubType roleSubType, BindingResult bindingResult, Model uiModel,
         HttpServletRequest httpServletRequest, Principal principal) {
	   updateRelatedInfo(roleSubType);
      if (bindingResult.hasErrors()) {
         populateEditForm(uiModel, roleSubType);
         return "rolesubtype/create";
      }
      uiModel.asMap().clear();
      roleSubType.setLastModificationUserId(principal.getName());
      roleSubTypeService.saveRoleSubType(roleSubType);
      return "redirect:/rolesubtype/view/" + encodeUrlPathSegment(roleSubType.getId().toString(), httpServletRequest);
   }

   @RequestMapping(value = "/create", produces = "text/html", method = RequestMethod.GET)
   public String createForm(Model uiModel) {
      populateEditForm(uiModel, new RoleSubType());
      return "rolesubtype/create";
   }

   @RequestMapping(value = "/view/{id}", produces = "text/html", method = RequestMethod.GET)
   public String show(@PathVariable("id") Long id, Model uiModel) {
      addDateTimeFormatPatterns(uiModel);
      uiModel.addAttribute("roleSubType", roleSubTypeService.findRoleSubType(id));
      uiModel.addAttribute("itemId", id);
      return "rolesubtype/show";
   }

   @RequestMapping(produces = "text/html")
   public String list(@RequestParam(value = "page", required = false) Integer page,
         @RequestParam(value = "size", required = false) Integer size, Model uiModel) {
      String forward = listRoleSubType(page, size, uiModel,"");
      return forward;
   }

   @RequestMapping(method = RequestMethod.PUT, produces = "text/html")
   public String update(@Valid RoleSubType roleSubType, BindingResult bindingResult, Model uiModel,
         HttpServletRequest httpServletRequest, Principal principal) {
	   updateRelatedInfo(roleSubType);
	   if (bindingResult.hasErrors()) {
         populateEditForm(uiModel, roleSubType);
         return "rolesubtype/update";
      }
      uiModel.asMap().clear();
      roleSubType.setLastModificationUserId(principal.getName());
      roleSubTypeService.updateRoleSubType(roleSubType);
      return "redirect:/rolesubtype/view/" + encodeUrlPathSegment(roleSubType.getId().toString(), httpServletRequest);
   }

   @RequestMapping(value = "/update/{id}", produces = "text/html", method = RequestMethod.GET)
   public String updateForm(@PathVariable("id") Long id, Model uiModel) {
      populateEditForm(uiModel, roleSubTypeService.findRoleSubType(id));
      return "rolesubtype/update";
   }

   @RequestMapping(value = "/{id}", method = RequestMethod.DELETE, produces = "text/html")
   public String delete(@PathVariable("id") Long id, @RequestParam(value = "page", required = false) Integer page,
         @RequestParam(value = "size", required = false) Integer size, Model uiModel, Principal principal) {
      RoleSubType roleSubType = roleSubTypeService.findRoleSubType(id);
      String errorMessageKey = null;
      String message = "";
      try {
         roleSubType.setLastModificationUserId(principal.getName());
         if(!roleSubTypeService.CheckIsUse(id)){
        	 roleSubTypeService.deleteRoleSubType(roleSubType);
        	 uiModel.asMap().clear();
         }
         else
        	 message = ROLE_SUB_TYPE_IS_USE;
      }
      catch (CannotDeleteObjectException e) {
         errorMessageKey = e.getMessage();
      }
      if (errorMessageKey != null) {
         uiModel.addAttribute("messageError", messageSource.getMessage(errorMessageKey,
               new String[] { roleSubType.getName() }, "CannotDeleteObjectException", null));
      }
      String forward = listRoleSubType((page == null) ? 1 : page, (size == null) ? 10 : size, uiModel,message);
      return forward;
   }
  
  private String listRoleSubType(Integer page, Integer size, Model uiModel,String message) {
      if (page != null || size != null) {
         int sizeNo = size == null ? 10 : size.intValue();
         final int firstResult = page == null ? 0 : (page.intValue() - 1) * sizeNo;
         uiModel.addAttribute("roleSubType", roleSubTypeService.findRoleSubTypeEntries(firstResult, sizeNo));
         float nrOfPages = (float) roleSubTypeService.countAllRoleSubType() / sizeNo;
         uiModel.addAttribute("maxPages", (int) ((nrOfPages > (int) nrOfPages || nrOfPages == 0.0) ? nrOfPages + 1
               : nrOfPages));
      }
      else {
         uiModel.addAttribute("roleSubType", roleSubTypeService.findAllRoleSubType());
      }
      addDateTimeFormatPatterns(uiModel);
      if(message!="")
    	  uiModel.addAttribute("message", message);
      else 
    	  uiModel.addAttribute("message", "");
      return "rolesubtype/list";
   }

   void addDateTimeFormatPatterns(Model uiModel) {
      uiModel.addAttribute("roleSubTypeControl_modificationdate_date_format",
            DateTimeFormat.patternForStyle("M-", LocaleContextHolder.getLocale()));
   }

   void populateEditForm(Model uiModel, RoleSubType roleSubType) {
      uiModel.addAttribute("roleSubType", roleSubType);
      uiModel.addAttribute("roletypes",referenceService.findAllRoleType());
      
      addDateTimeFormatPatterns(uiModel);
   }

   String encodeUrlPathSegment(String pathSegment, HttpServletRequest httpServletRequest) {
      String enc = httpServletRequest.getCharacterEncoding();
      if (enc == null) {
         enc = WebUtils.DEFAULT_CHARACTER_ENCODING;
      }
      try {
         pathSegment = UriUtils.encodePathSegment(pathSegment, enc);
      }
      catch (UnsupportedEncodingException uee) {
      }
      return pathSegment;
   }
   
   @RequestMapping(value = "/searchaccesscontrol", method = RequestMethod.GET, produces = "text/html")
   public String searchAccessControlForm(Model uiModel) {
	
	   uiModel.addAttribute("access", new SearchAccessControl());
	   return "rolesubtype/accesscontrolSearch";
   }

   @RequestMapping(value = "/searchaccesscontrol", method = RequestMethod.POST, produces = "text/html")
   public String searchAccessControl(SearchAccessControl searchAccessControl, Model uiModel) {
      List<AccessControl> access = null;
      String name = searchAccessControl.getSearchAccessControl();
      if (name == null) {
         name = "";
      }
      access = accesscontrolServce.findAccessControlbyLikeName(name);
      uiModel.addAttribute("accesscontrol", access);

      return "rolesubtype/controlSearchResult";
   }

   @RequestMapping(value = "/searchaccesscontrol/selected", method = RequestMethod.POST)
   public String searchACL(@Param("idsSelected") String idsSelected,
         Model uiModel) {
      List<AccessControl> acls = new ArrayList<AccessControl>();
      if (idsSelected != null && idsSelected.trim().length() > 0) {
         String[] idStrs = idsSelected.split("\\|");
         List<String> processedIds = new ArrayList<String>();
         for (String idStr : idStrs) {
            if(!processedIds.contains(idStr)){
               processedIds.add(idStr);
               if (idStr.trim().length() > 0) {
                  AccessControl acl = accesscontrolServce.findAccessControl(Long.parseLong(idStr));
                  if (acl != null) {
                     acls.add(acl);
                  }
               }
            }
         }
      }
      uiModel.addAttribute("acls", acls);
      return "rolesubtype/searchaccesscontrolselected";
   }

   @RequestMapping(value = "/searchaccesscontrol/exclude", method = RequestMethod.POST)
   public String searchRoleExclude(
         @Param("idsSelected") String idsSelected,
         @Param("excludedId") String excludedId, Model uiModel) {
      List<AccessControl> acls = new ArrayList<AccessControl>();
      if (idsSelected != null && idsSelected.trim().length() > 0) {
         String[] idStrs = idsSelected.split("\\|");
         List<String> processIds = new ArrayList<String>();
         for (String idStr : idStrs) {
            if (!processIds.contains(idStr)) {
               processIds.add(idStr);
               if (idStr.trim().length() > 0 && !idStr.equals(excludedId)) {
                  AccessControl acl = accesscontrolServce.findAccessControl(Long.parseLong(idStr));
                  if (acl != null) {
                     acls.add(acl);
                  }
               }
            }
         }
      }
      uiModel.addAttribute("acls", acls);
      return "rolesubtype/searchaccesscontrolselected";
   }
   
   private void updateRelatedInfo(RoleSubType roleSubtype){
	   List<AccessControl> acls = roleSubtype.getAccessControl();
	   if(acls != null && acls.size() > 0){
	      for(int i = 0; i < acls.size(); i++){
	         AccessControl acl = acls.get(i);
	         acl = accesscontrolServce.findAccessControl(acl.getId());
	         acls.set(i, acl);
	      }
	   }	   
	 
	}



}
